﻿using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.Extensions.Primitives;

namespace RuoVea.OmiApi.Reports.Dto;

/// <summary>
/// 使用Dictionary<string, string>动态获取前端传参
/// 避免使用Dictionary接收参数时需要前端如此传参：param.Item1=aaa&param.Item2=bbb
/// 使用方法: Controller方法参数增加： [ModelBinder(BinderType = typeof(DictionaryBinder))] Dictionary<string, string> param参数名称
/// </summary>
public class DictionaryBinder : IModelBinder
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="bindingContext"></param>
    /// <returns></returns>
    /// <exception cref="ArgumentNullException"></exception>
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
        {
            throw new ArgumentNullException(nameof(bindingContext));
        }

        Dictionary<string, string> result = new();

        var request = bindingContext.HttpContext.Request;
        var parameter = bindingContext.ModelMetadata.ParameterName;
        var value = "";

        if (bindingContext.ModelType == typeof(Dictionary<string, string>))
        {
            AddDictionary(request.Query, ref result);
            if (request.HasFormContentType)
            {
                AddDictionary(request.Form, ref result);
            }
        }
        bindingContext.Result = ModelBindingResult.Success(result);
        return Task.CompletedTask;
    }

    private void AddDictionary<T>(T keyPair, ref Dictionary<string, string> dict) where T : IEnumerable<KeyValuePair<string, StringValues>>
    {
        foreach (var item in keyPair)
        {
            if (!dict.ContainsKey(item.Key) && !string.IsNullOrWhiteSpace(item.Key) && !string.IsNullOrEmpty(item.Value))
            {
                dict.Add(item.Key, item.Value);    //Pascal 命名法
            }
        }
    }
}